/*
******************************************************************************************************* 
**  Copyright (C) 2019, 苏州检易生物科技有限公司 
**  All rights reserved. 
** 
**  FileName:       	uart.c
**  Description:	
**  Author:        	 
**  Version				v0.1
**  Date:           	2019-05-30
**	Function List： 
**  History:         
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	调试开关
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "eth.h"
#include "log_console.h"
/*
*********************************************************************************************************
*                                              	宏定义
*********************************************************************************************************
*/
#define TCP_CONNECT_TIMEOUT	10000
#define TCP_BREATHE_PERIOD	2000
/*
*********************************************************************************************************
*                                              	结构体定义
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                              	函数原型声明
*********************************************************************************************************
*/
static void ETH_BSP_Config(void);
static void ETH_BSP_GPIO_INIT(void);
static void ETH_BSP_NVIC_INIT(void);
static void ETH_BSP_DMA_INIT(void);
static void NETMPU_Config(void);
/*
*********************************************************************************************************
*                                              	全局变量定义
*********************************************************************************************************
*/

__attribute__((at(0x30040000))) ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
__attribute__((at(0x30040060))) ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
__attribute__((at(0x30040200))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffer */
__attribute__((at(0x30041A00))) uint8_t Tx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffer */


ETH_HandleTypeDef LAN8720_ETHHandle;
/*
*********************************************************************************************************
*                                              	模块静态变量定义
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*                                              	函数定义
*********************************************************************************************************
*/

eth_err_t eth_open(void)
{
	ETH_BSP_Config();
	return ETH_ERR_NONE;
}
eth_err_t	eth_close()
{
	return ETH_ERR_NONE;
}

static void ETH_BSP_Config(void)
{
	uint8_t  res=0;
	uint32_t read;
	NETMPU_Config();
	
	ETH_BSP_GPIO_INIT();
	ETH_BSP_NVIC_INIT();
	ETH_BSP_DMA_INIT();	
	
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);
	rt_thread_delay(2000);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);
	
	//TBD 硬件复位
//	res|=HAL_ETH_WritePHYRegister(&LAN8720_ETHHandle,LAN8720_ADDR,LAN8720_BCR,LAN8720_BCR_SOFT_RESET);
//	if(res!=HAL_OK)
//	{
//		Trace_Log("LAN8720 write reg err!\n");
//		return;
//	}
	rt_thread_delay(500);
	res|=HAL_ETH_ReadPHYRegister(&LAN8720_ETHHandle,LAN8720_ADDR,LAN8720_BCR,&read);
//	if(res!=HAL_OK)
//	{
//		Trace_Log("LAN8720 soft reset err!\n");
//		return;
//	}
	read|=LAN8720_BCR_AUTONEGO_EN;
	res|=HAL_ETH_WritePHYRegister(&LAN8720_ETHHandle,LAN8720_ADDR,LAN8720_BCR,read);
	if(res!=HAL_OK)
	{
//		Trace_Log("LAN8720 reset err!\n");
		return;
	}
	rt_thread_delay(500);

	uint16_t timeout=0;
	while(LAN8720_GetLinkState()<=LAN8720_STATUS_LINK_DOWN)  
	{
		rt_thread_delay(10);
		timeout+=10;
		if(timeout>=LAN8720_TIMEOUT) 
		{
			return;
		}
	}
	
	ETH_MACConfigTypeDef MACConf;
	HAL_ETH_GetMACConfig(&LAN8720_ETHHandle,&MACConf); 
	switch (LAN8720_GetLinkState())
	{
		case LAN8720_STATUS_100MBITS_FULLDUPLEX:    //100M全双工
				MACConf.DuplexMode=ETH_FULLDUPLEX_MODE;
				MACConf.Speed=ETH_SPEED_100M;
				break;
		case LAN8720_STATUS_100MBITS_HALFDUPLEX:    //100M半双工
				MACConf.DuplexMode=ETH_HALFDUPLEX_MODE;
				MACConf.Speed=ETH_SPEED_100M;
				break;
		case LAN8720_STATUS_10MBITS_FULLDUPLEX:     //10M全双工
				MACConf.DuplexMode=ETH_FULLDUPLEX_MODE;
				MACConf.Speed=ETH_SPEED_10M;
				break;
		case LAN8720_STATUS_10MBITS_HALFDUPLEX:     //10M半双工
				MACConf.DuplexMode=ETH_HALFDUPLEX_MODE;
				MACConf.Speed=ETH_SPEED_10M;
				break;
		default:
				break;      
	}
	HAL_ETH_SetMACConfig(&LAN8720_ETHHandle,&MACConf);
	HAL_ETH_Start(&LAN8720_ETHHandle);
	HAL_ETH_Start_IT(&LAN8720_ETHHandle);
}
static void ETH_BSP_GPIO_INIT(void)
{
	GPIO_InitTypeDef GPIO_Initure;

	__HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_GPIOC_CLK_ENABLE();
	__HAL_RCC_GPIOD_CLK_ENABLE();
	__HAL_RCC_GPIOG_CLK_ENABLE();
	__HAL_RCC_ETH1MAC_CLK_ENABLE();
	__HAL_RCC_ETH1TX_CLK_ENABLE();
	__HAL_RCC_ETH1RX_CLK_ENABLE();
	
	//新板子的复位引脚
	__HAL_RCC_GPIOB_CLK_ENABLE();
	GPIO_Initure.Pin=GPIO_PIN_0;
	GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
	GPIO_Initure.Pull=GPIO_PULLUP;
	GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
	HAL_GPIO_Init(GPIOB,&GPIO_Initure);
	
	
	GPIO_Initure.Pin=GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_7; 
	GPIO_Initure.Mode=GPIO_MODE_AF_PP;
	GPIO_Initure.Pull=GPIO_NOPULL;
	GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;
	GPIO_Initure.Alternate=GPIO_AF11_ETH;
	HAL_GPIO_Init(GPIOA,&GPIO_Initure);

	/*新板子的网口引脚 PB12 PB13*/
	GPIO_Initure.Pin=GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13;
	HAL_GPIO_Init(GPIOB,&GPIO_Initure);

	GPIO_Initure.Pin=GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5;
	HAL_GPIO_Init(GPIOC,&GPIO_Initure);
}
static void ETH_BSP_NVIC_INIT(void)
{
	HAL_NVIC_SetPriority(ETH_IRQn,1,1);
	HAL_NVIC_EnableIRQ(ETH_IRQn);
}
static void ETH_BSP_DMA_INIT(void)
{
//	uint8_t MAC_ADDR[6]={m_system_cfg.mac_addr0,m_system_cfg.mac_addr1,m_system_cfg.mac_addr2,m_system_cfg.mac_addr3,m_system_cfg.mac_addr4,m_system_cfg.mac_addr5};
	uint8_t MAC_ADDR[6]={DEFAULT_MAC_ADDR0,DEFAULT_MAC_ADDR1,DEFAULT_MAC_ADDR2,DEFAULT_MAC_ADDR3,DEFAULT_MAC_ADDR4,DEFAULT_MAC_ADDR5};
	LAN8720_ETHHandle.Instance=ETH;
	LAN8720_ETHHandle.Init.MACAddr=MAC_ADDR;
	LAN8720_ETHHandle.Init.MediaInterface=HAL_ETH_RMII_MODE;
	LAN8720_ETHHandle.Init.RxDesc=DMARxDscrTab;
	LAN8720_ETHHandle.Init.TxDesc=DMATxDscrTab;
	LAN8720_ETHHandle.Init.RxBuffLen=ETH_MAX_PACKET_SIZE;
	if(HAL_ERROR == HAL_ETH_Init(&LAN8720_ETHHandle))
	{
		Critical_Log("Eth bsp init err!\r\n");
		return;
	}
	HAL_ETH_SetMDIOClockRange(&LAN8720_ETHHandle);
	
	for(uint8_t idx=0;idx<ETH_RX_DESC_CNT;idx ++)
	{
		HAL_ETH_DescAssignMemory(&LAN8720_ETHHandle,idx,Rx_Buff[idx],NULL);
		WRITE_REG( ((ETH_DMADescTypeDef *)LAN8720_ETHHandle.TxDescList.TxDesc[idx])->DESC0 , (uint32_t)Tx_Buff[idx] );
		WRITE_REG( ((ETH_DMADescTypeDef *)LAN8720_ETHHandle.TxDescList.TxDesc[idx])->BackupAddr0 , (uint32_t)Tx_Buff[idx] );
	}
}
void NETMPU_Config(void)
{
	MPU_Region_InitTypeDef MPU_InitStruct={0};

	HAL_MPU_Disable();
//	MPU_InitStruct.Enable=MPU_REGION_ENABLE;
//	MPU_InitStruct.BaseAddress=0x30040000;
//	MPU_InitStruct.Size=MPU_REGION_SIZE_16KB;//MPU_REGION_SIZE_256B;
//	MPU_InitStruct.AccessPermission=MPU_REGION_FULL_ACCESS;
//	MPU_InitStruct.IsBufferable=MPU_ACCESS_BUFFERABLE;
//	MPU_InitStruct.IsCacheable=MPU_ACCESS_NOT_CACHEABLE;
//	MPU_InitStruct.IsShareable=MPU_ACCESS_SHAREABLE;
//	MPU_InitStruct.Number=MPU_REGION_NUMBER5;
//	MPU_InitStruct.TypeExtField=MPU_TEX_LEVEL0;
//	MPU_InitStruct.SubRegionDisable=0x00;
//	MPU_InitStruct.DisableExec=MPU_INSTRUCTION_ACCESS_ENABLE;
//	HAL_MPU_ConfigRegion(&MPU_InitStruct); 
//	HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
		
	MPU_InitStruct.Enable = MPU_REGION_ENABLE;
	MPU_InitStruct.BaseAddress = 0X30040000;
	MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
	MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
	MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
	MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
	MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
	MPU_InitStruct.Number = MPU_REGION_NUMBER0;
	MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
	MPU_InitStruct.SubRegionDisable = 0x00;
	MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
	
	MPU_InitStruct.Enable = MPU_REGION_ENABLE;
	MPU_InitStruct.BaseAddress = 0X30044000;
	MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
	MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
	MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
	MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
	MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
	MPU_InitStruct.Number = MPU_REGION_NUMBER1;
	MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
	MPU_InitStruct.SubRegionDisable = 0x00;
	MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
	
  /* Enables the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
void ETH_IRQHandler(void)
{
	rt_interrupt_enter();
	LwIP_Pkt_Handle();
	__HAL_ETH_DMA_CLEAR_IT(&LAN8720_ETHHandle,ETH_DMA_NORMAL_IT);
	__HAL_ETH_DMA_CLEAR_IT(&LAN8720_ETHHandle,ETH_DMA_RX_IT);
	__HAL_ETH_DMA_CLEAR_IT(&LAN8720_ETHHandle,ETH_DMA_TX_IT); 
	rt_interrupt_leave();
}

uint32_t LAN8720_GetLinkState(void)
{
	uint8_t res=0;
	uint32_t readval=0;
	res|=HAL_ETH_ReadPHYRegister(&LAN8720_ETHHandle,LAN8720_ADDR,LAN8720_BSR,&readval);
  if(res!=HAL_OK||(readval&LAN8720_BSR_LINK_STATUS)==0)
	{
//		ErrorLog("Read LAN BSR 0x%0x!\r\n",readval);
//		res|=HAL_ETH_WritePHYRegister(&LAN8720_ETHHandle,LAN8720_ADDR,LAN8720_BCR,readval);
//		ErrorLog("Read LAN BCR 0x%0x!\r\n",readval);
		return LAN8720_STATUS_LINK_DOWN;
	}

  res|=HAL_ETH_ReadPHYRegister(&LAN8720_ETHHandle,LAN8720_ADDR,LAN8720_BCR,&readval);
	if((readval&LAN8720_BCR_AUTONEGO_EN)!=LAN8720_BCR_AUTONEGO_EN)
	{
		if(((readval&LAN8720_BCR_SPEED_SELECT)==LAN8720_BCR_SPEED_SELECT)&&
						((readval&LAN8720_BCR_DUPLEX_MODE)==LAN8720_BCR_DUPLEX_MODE)) 
				return LAN8720_STATUS_100MBITS_FULLDUPLEX;
		else if((readval&LAN8720_BCR_SPEED_SELECT)==LAN8720_BCR_SPEED_SELECT)
				return LAN8720_STATUS_100MBITS_HALFDUPLEX;
		else if((readval&LAN8720_BCR_DUPLEX_MODE)==LAN8720_BCR_DUPLEX_MODE)
				return LAN8720_STATUS_10MBITS_FULLDUPLEX;
		else
				return LAN8720_STATUS_10MBITS_HALFDUPLEX;
	}
	else 
	{
		res|=HAL_ETH_ReadPHYRegister(&LAN8720_ETHHandle,LAN8720_ADDR,LAN8720_PHYSCSR,&readval);
		if((readval&LAN8720_PHYSCSR_AUTONEGO_DONE)==0)
				return LAN8720_STATUS_AUTONEGO_NOTDONE;
		if((readval&LAN8720_PHYSCSR_HCDSPEEDMASK)==LAN8720_PHYSCSR_100BTX_FD)
				return LAN8720_STATUS_100MBITS_FULLDUPLEX;
		else if ((readval&LAN8720_PHYSCSR_HCDSPEEDMASK)==LAN8720_PHYSCSR_100BTX_HD)
				return LAN8720_STATUS_100MBITS_HALFDUPLEX;
		else if ((readval&LAN8720_PHYSCSR_HCDSPEEDMASK)==LAN8720_PHYSCSR_10BT_FD)
				return LAN8720_STATUS_10MBITS_FULLDUPLEX;
		else
				return LAN8720_STATUS_10MBITS_HALFDUPLEX;         
	}
}
void LAN8720_SetLinkState(uint32_t linkstate)
{
	uint32_t readval=0;
	uint32_t res=0;
	res|=HAL_ETH_ReadPHYRegister(&LAN8720_ETHHandle,LAN8720_ADDR,LAN8720_BCR,&readval);
	readval&=~(LAN8720_BCR_AUTONEGO_EN|LAN8720_BCR_SPEED_SELECT|LAN8720_BCR_DUPLEX_MODE);
	if(linkstate==LAN8720_STATUS_100MBITS_FULLDUPLEX)       //100M全双工
			readval|=(LAN8720_BCR_SPEED_SELECT|LAN8720_BCR_DUPLEX_MODE);
	else if(linkstate==LAN8720_STATUS_100MBITS_HALFDUPLEX)  //100M半双工
			readval|=LAN8720_BCR_SPEED_SELECT; 
	else if(linkstate==LAN8720_STATUS_10MBITS_FULLDUPLEX)   //10M全双工
			readval|=LAN8720_BCR_DUPLEX_MODE;
	res|=HAL_ETH_WritePHYRegister(&LAN8720_ETHHandle,LAN8720_ADDR,LAN8720_BCR,readval);
}